<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>02-this指向的理解</title>
</head>

<body>
    <button id="btn">点我</button>
    <script>
        /*
            普通函数调用
                开启严格模式：this的值是undefined
                不开启严格模式：this的值是window
            对象调用
                this的值是调用者
            call/apply/bind方式调用
                this的值是call/apply/bind调用的时候传入的第一个参数
            构造函数
                this的值是产生的实例对象
            箭头函数
                没有自己的this，this的值取得是外侧作用域下this的值
            回调函数(定时、数组循环、DOM事件、Ajax)
                定时、数组循环、Ajax this的值是window
                DOM事件的this的值是：事件源

            问题一：call/apply/bind方式调用区别
                作用：
                    强行改变this指向
                    call/apply
                        直接函数调用
                        call/apply调用的时候不传递参数，最终被借调函数this的值是 window
                        call/apply调用的时候传递第一个参数是null/undefined，最终被借调函数this的值是 window
                        call/apply调用的时候传递第一个参数是基本数据类型，最终被借调函数this的值是 该基本数据类型的包装对象
                        call/apply调用的时候传递第一个参数是引用数据类型，最终被借调函数this的值是 传递的该引用类型的数据
                        call可以接收0-n个参数
                            第一个参数就是要强行改变为的this的值
                            从第二个参数开始，后面的参数都会当成被借调函数的实参
                        apply可以接收0-2个参数
                            第一个参数就是要强行改变为的this的值
                            第二个参数只能是个数组，数组里的所有数据都会当成被借调函数的实参

                    bind
                        函数不会直接调用，而是返回一新函数,新函数的this指向已经被强行改变
                        bind调用时候的一些细节和call一样

            问题二：构造函数的细节点
                构造函数内部如果设置返回值
                    返回基本数据类型
                        最终还是会生成实例化对象
                    返回引用数据类型数据
                        最终生成是返回该引用数据类型的值

        */
        // "use strict"
        // function fn() {
        //     console.log(this)
        // }
        // fn()
        // var obj = {
        //     fn: function () {
        //         console.log(this)
        //     },
        //     person: {
        //         say: function () {
        //             console.log(this)
        //         }
        //     }
        // }
        // // obj.fn()
        // // obj.person.say()
        // let say = obj.person.say;
        // say()
        // function fn() {
        //     console.log(this)
        // }
        // var obj = {}

        // fn.call(obj)
        // function Person() {
        //     this.name = '123'
        //     console.log(this)
        // }
        // let p = new Person()
        // console.log(p)
        // setTimeout(function () {
        //     console.log(this)
        // });
        // const btn = document.getElementById('btn')
        // btn.onclick = function () {
        //     console.log(this)
        // }

        // function fn(a, b, c) {
        //     console.log(a, b, c)
        //     console.log(this)
        // }
        // var obj = {}
        // // fn.apply(obj, [2, 3, 4])
        // let result = fn.bind(obj, 3, 4, 5)
        // result('aa', 'bb')

        function Person() {

            return {}

        }
        let p = new Person()
        console.log(p)

    </script>
</body>

</html>